//
//  UITableView_register.swift
//  MyLibrary
//
//  Created by 周博 on 2020/6/18.
//  Copyright © 2020 ncit. All rights reserved.
//

import UIKit

extension UITableView {

    /// TableView注册cell 注册可以不写id, 使用Target名.cell名作为id
    /// 注册class和id都是 target.class,  注册nib只有class, 否则找不到名为target.class的nib, 这个要注意


    /**
     * nibCellClass: String(describing: XXX.self) / String(describing: XXX.classForCoder()) 这样不会带有target名
     * xxxClass.description, NSStringFromClass(xxx.classForCoder)  target名.cell名
     */
    func registerCell(nibCellClass: AnyClass, identifier: String? = nil) {

        // registerNib对于nibName做了一个处理, 外界只要传class(即target.class)即可, 方法内部处理
        let nib = UINib(nibName: String(describing: nibCellClass.self), bundle: nil)
        register(nib, forCellReuseIdentifier: identifier ?? nibCellClass.description())
    }
    
    
    /**
     * 如果有nib, 注册nib, 否则注册cellClass
     */
    func registerCell(cellClass: AnyClass, identifier: String? = nil) {
        
        // 获取不带有target的cell名string
        let cellName = String(describing: cellClass.self)
        
        // 判断是否有对应的xib, 如果有, 注册xib, 否则注册cell
        // mlgb, 之前写 "cellName = cellClass.description(), \(cellName).xib" path一直拿不到...
        let path = Bundle.main.path(forResource: "\(cellName).nib", ofType: nil)

        if path == nil {
            register(cellClass, forCellReuseIdentifier: identifier ?? cellClass.description())
        } else {
            self.registerCell(nibCellClass: cellClass)
        }
    }

    /**
     * dequeueCell
     * xxxxxxxxxxx: T泛型不支持类类型约束, 所以用tableview暂时没啥好办法
     *     解决办法: T.Type做类型约束.....
     *     T.type是T的源类型, 也就是类型的类型, cellClass是T这个类型的类型的一个对象, 意思就是T.  就类似于 number: Int, number是Int类型对象
     *
     * 这样搞好之后, 只要调用dequeueCell即可, 不需要注册cell, 返回的类型也是传入的cellClass类型, 不用外界自己转  很方便
     *
     * 调用方法: (推荐第二种, 不需要强转)
     * 1. tableView.dequeueCell(cellClass: ATableViewCell.classForCoder() as! ATableViewCell.Type)
     *
     * 2. tableView.dequeueCell(cellClass: ATableViewCell.self)
     *
     *
     * classForCoder, self 知识扩充:
     * let a: A.Type = A.self
     * classForCoder和A.type一个类型, 都是元类型
     *
     * AnyClass = AnyObject.Type
     * xxx.classforCoder 获取到的是AnyClass对象, 即 AnyObject.Type对象, 但是AnyObject需要as成想要的xxx类
     * 而用 xxx.self 直接会去到的就是 xxx.Type对象
     *
     * 在本方法中: <T: UITableViewCell> T是UITableViewCell类的对象 cellClass是 UITableViewCell.Type类对象
     *
     *
     */
    func dequeueCell<T: UITableViewCell>(cellClass: T.Type) -> T {

        if let cell = self.dequeueReusableCell(withIdentifier: cellClass.description()) as? T {

            return cell
        }

        // 如果没有取到cell, 注册cell
        registerCell(cellClass: cellClass)

        return self.dequeueReusableCell(withIdentifier: T.description()) as! T
    }
}

